#include <iostream>
#include <cstdio>
#include <signal.h>
#include <unistd.h>


// 易变关键字
// volatile int flag = 0;//防止编译器优化，取出对应的flag值必须从内存中区取出，而不是从寄存器中取出，volatile保证内存可见性

// void change(int signo) // 信号捕捉的执行流
// {
//     (void)signo;

//     flag = 1;
//     printf("change flag 0->1, getpid: %d\n", getpid());
// }

// int main()
// {
//     printf("I am main process, pid is : %d\n", getpid());
//     signal(2, change);

//     while(!flag); // 主执行流--- flag我们没有做任何修改！
//     printf("我是正常退出的!\n");
// }


void PrintBlock()
{
    sigset_t block,oblock;
    sigemptyset(&block);
    sigemptyset(&oblock);
    
    sigprocmask(SIG_BLOCK,&block,&oblock);
    std::cout << "block: ";
    for(int signo = 31;signo > 0;signo--)
    {
        if(sigismember(&oblock,signo))
        {
            std::cout << 1;
        }
        else 
        {
            std::cout << 0;
        }
    }
    std::cout << std::endl;
}
 
void PrintPending()
{
    sigset_t pending;
    ::sigpending(&pending);

    std::cout << "Pending: ";
    for (int signo = 31; signo > 0; signo--)
    {
        if (sigismember(&pending, signo))
        {
            std::cout << 1;
        }
        else
        {
            std::cout << 0;
        }
    }
    std::cout << std::endl;
}

void Handler(int signo)
{
    static int cnt = 0;
    cnt++;
    //int a = 0;
    while(true)
    {
        std::cout << "get a signal : " << signo << "，cnt : " << cnt <<std::endl;
        PrintBlock();
        PrintPending();
        sleep(1);
        // a++;
        // if(a == 5)
        // {
        //     break;
        // }
        //break;
    }
}

int main()
{
    struct sigaction act,oact;
    act.sa_handler = Handler;
    
    sigemptyset(&act.sa_mask);

    sigaddset(&act.sa_mask,2);
    sigaddset(&act.sa_mask,3);
    sigaddset(&act.sa_mask,4);
    sigaddset(&act.sa_mask,5);
    sigaddset(&act.sa_mask,6);

    sigaction(2,&act,&oact);//屏蔽信号掩码在处理完handler方法就会恢复,pending在执行完handler方法之前就已经恢复了
    //在执行handler方法时候，如果再次发送信号，不会执行handler方法，而是把对应的pending表中对应信号位置为1
    while(true)
    {
        //PrintPending();
        //PrintBlock();
        pause();
    }
    return 0;
}